package org.jacp.demo.io;

import java.io.IOException;
import java.io.InputStream;


public final class MeasuredInputStream extends InputStream {
	private InputStream in;
	private long read = 0;
	
	public MeasuredInputStream(InputStream i) {
		this.in = i;
	}

	public final int available() throws IOException {
		return in.available();
	}
	
	/** Returns the number of bytes that have been read (or skipped).
	 * 
	 * @return the number of bytes that have been read (or skipped).
	 */
	public final long getReadBytes() {
		return read;
	}

	public final void close() throws IOException {
		in.close();
	}

	public final synchronized void mark(int readlimit) {
		throw new RuntimeException();
	}

	public final boolean markSupported() {
		return false;
	}

	public final int read() throws IOException {
		final int k = in.read();
		if(k==-1)
			return -1;
		read++;
		return k;
	}

	public final int read(byte[] b, int off, int len) throws IOException {
		final int returnValue = in.read(b, off, len);
		if(returnValue==-1)
			return -1;
		read += returnValue;
		
		return returnValue;
	}

	public final int read(byte[] b) throws IOException {
		return read(b,0,b.length);
	}

	public final synchronized void reset() throws IOException {
		throw new RuntimeException();
	}

	public final long skip(long n) throws IOException {
		final long returnValue = in.skip(n);
		if(returnValue==-1)
			return -1;
		read += returnValue;
		
		return returnValue;
	}

	/** This skips forward to the requested position.
	 * If the requested position is less than the current
	 * position, then an exception is thrown.
	 * @param pos
	 * @throws IOException
	 */
	public final void seek(long pos) throws IOException {
		if(pos==read) return;
		if(pos<read) throw new IOException("Cannot seek backwards.");
		skip(pos-read);
	}
}
